
package com.gitee.jmash.oidc.oauth2.jaxrs;

import com.gitee.jmash.oidc.oauth2.enums.GrantType;
import com.gitee.jmash.oidc.oauth2.impl.ClientCredentialsImpl;
import com.gitee.jmash.oidc.oauth2.impl.OauthCodeTokenImpl;
import com.gitee.jmash.oidc.oauth2.impl.OauthPasswordImpl;
import com.gitee.jmash.oidc.oauth2.impl.OauthRefreshTokenImpl;
import com.gitee.jmash.oidc.oauth2.models.ClientCredentialsModel;
import com.gitee.jmash.oidc.oauth2.models.ErrorResponse;
import com.gitee.jmash.oidc.oauth2.models.TokenCodeModel;
import com.gitee.jmash.oidc.oauth2.models.TokenModel;
import com.gitee.jmash.oidc.oauth2.models.TokenPasswordModel;
import com.gitee.jmash.oidc.oauth2.models.TokenRefreshModel;
import jakarta.inject.Inject;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import jakarta.ws.rs.BeanParam;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;

/**
 * OAuth2.0 /oauth/token.
 *
 * @author CGD
 *
 */
@Path("/token")
public class TokenEndpoint {

  @Inject
  OauthCodeTokenImpl oauthCodeTokenImpl;

  @Inject
  OauthRefreshTokenImpl oauthRefreshTokenImpl;

  @Inject
  OauthPasswordImpl oauthPasswordImpl;

  @Inject
  ClientCredentialsImpl clientCredentialsImpl;

  /** /oauth/token authorization_code/refresh_token Type Request. */
  @POST
  @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
  @Produces(MediaType.APPLICATION_JSON)
  public Response token(@Valid @BeanParam TokenModel token, @Context HttpServletRequest request) {
    token.setAuthorization(token.getAuthorization());
    if (GrantType.authorization_code.equals(token.getGrantType())) {
      TokenCodeModel codeModel = new TokenCodeModel();
      codeModel.setGrantType(token.getGrantType());
      codeModel.setClientId(token.getClientId());
      codeModel.setClientSecret(token.getClientSecret());
      codeModel.setCode(token.getCode());
      return oauthCodeTokenImpl.token(codeModel, request);
    } else if (GrantType.refresh_token.equals(token.getGrantType())) {
      TokenRefreshModel codeModel = new TokenRefreshModel();
      codeModel.setGrantType(token.getGrantType());
      codeModel.setClientId(token.getClientId());
      codeModel.setClientSecret(token.getClientSecret());
      codeModel.setRefreshToken(token.getRefreshToken());
      codeModel.setScope(token.getScope());
      return oauthRefreshTokenImpl.token(codeModel, request);
    } else if (GrantType.password.equals(token.getGrantType())) {
      TokenPasswordModel codeModel = new TokenPasswordModel();
      codeModel.setGrantType(token.getGrantType());
      codeModel.setClientId(token.getClientId());
      codeModel.setClientSecret(token.getClientSecret());
      codeModel.setUsername(token.getUsername());
      codeModel.setPassword(token.getPassword());
      return oauthPasswordImpl.token(codeModel, request);
    } else if (GrantType.client_credentials.equals(token.getGrantType())) {
      ClientCredentialsModel codeModel = new ClientCredentialsModel();
      codeModel.setGrantType(token.getGrantType());
      codeModel.setClientId(token.getClientId());
      codeModel.setClientSecret(token.getClientSecret());
      codeModel.setScope(token.getScope());
      return clientCredentialsImpl.token(codeModel, request);
    }
    return ErrorResponse.createResponse("invalid_grant", "invalid_grant不匹配.");
  }

}
